﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LCA.Community.DAL.Model;
using LCA.Community.DAL.Interfaces;

namespace LCA.Community.DAL
{
    /// <summary>
    /// The repository for groups implemented using Windows Azure
    /// </summary>
    public class GroupsRepository : BaseRepository<Group>, IGroupsRepository
    {
        #region Fields
        private IGroupMembershipsRepository _groupMembershipRepository;
        private IUsersRepository _usersRepository;
        private IPostsRepository _postRepository;
        private IEventsRepository _eventsRepository;
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="GroupsRepository"/> class.
        /// </summary>
        /// <param name="groupMembershipRepository">The group membership repository.</param>
        /// <param name="usersRepository">The users repository.</param>
        public GroupsRepository (IDataServiceContext<Group> dataServiceContext, IGroupMembershipsRepository groupMembershipRepository,IUsersRepository usersRepository, IPostsRepository postRepository, IEventsRepository eventsRepository)
            :base(dataServiceContext)
        {
            _groupMembershipRepository = groupMembershipRepository;
            _usersRepository = usersRepository;
            _postRepository = postRepository;
            _eventsRepository = eventsRepository;
        }

        /// <summary>
        /// Adds the specified group.
        /// </summary>
        /// <param name="entity">The group.</param>
        public override void  Add(Group entity)
        {
            base.Add(entity);

            var membership = new GroupMembership(entity.Owner, entity.RowKey);
            _groupMembershipRepository.Add(membership);
        }

        /// <summary>
        /// Deletes the specified group.
        /// </summary>
        /// <param name="entity">The group.</param>
        public override void Delete(Group entity)
        {
            base.Delete(entity);

            _groupMembershipRepository.DeleteAllGroupMemberships(entity.RowKey);
            _postRepository.DeleteAllUserPosts(entity.RowKey);
            _eventsRepository.DeleteAllGroupsEvents(entity.RowKey);
        }


        /// <summary>
        /// Gets the name of the groups containing name.
        /// </summary>
        /// <param name="name">The name of the group.</param>
        /// <returns>List of groups containing the name.</returns>
        public List<Group> GetGroupsContainingName(string name)
        {
            return Entities.Where(g => g.Name.ToLower().Contains(name.ToLower())).ToList();
        }

        /// <summary>
        /// Gets the group members.
        /// </summary>
        /// <param name="groupID">The group ID.</param>
        /// <returns>The members of the group</returns>
        public List<User> GetGroupMembers(string groupID)
        {
            var groupMemberships = _groupMembershipRepository.GetGroupMembershipByGroup(groupID);

            return (from gm in groupMemberships
                    select _usersRepository.Get(gm.Member)).ToList();
        }

        /// <summary>
        /// Gets the groups by user.
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <returns>The groups that the user is member of.</returns>
        public List<Group> GetGroupsByUser(string userID)
        {
            var groupMemberships = _groupMembershipRepository.GetGroupMembershipByUser(userID);

            return (from gm in groupMemberships
                    select Get(gm.Group)).ToList();
        }

        /// <summary>
        /// Gets the 10 recent groups.
        /// </summary>
        /// <value>The 10 recent groups.</value>
        public List<Group> RecentGroups
        {
            get 
            {
                return Entities.OrderByDescending(g => g.Timestamp).Take(10).ToList();
            }
        }
    }
}
